package com.codeoss.module.workflow.service.impl;

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.codeoss.framework.expression.Expression;
import com.codeoss.framework.expression.IScriptServiceStore;
import com.codeoss.framework.service.impl.BaseService;
import com.codeoss.framework.workflow.context.WorkflowContext;
import com.codeoss.framework.workflow.def.NodeDef;
import com.codeoss.framework.workflow.def.WorkflowDef;
import com.codeoss.framework.workflow.service.INodeService;
import com.codeoss.framework.workflow.store.IWorkflowStore;
import com.codeoss.module.workflow.dao.WorkflowProcessMapper;
import com.codeoss.module.workflow.model.WorkflowActivity;
import com.codeoss.module.workflow.model.WorkflowProcess;
import com.codeoss.module.workflow.model.WorkflowToken;
import com.codeoss.module.workflow.model.WorkflowWorkflow;
import com.codeoss.module.workflow.service.IWorkflowActivityService;
import com.codeoss.module.workflow.service.IWorkflowProcessService;
import com.codeoss.module.workflow.service.IWorkflowWorkflowService;

@Service
public class WorkflowProcessService extends BaseService<WorkflowProcessMapper, WorkflowProcess>
		implements IWorkflowProcessService,ApplicationContextAware {
    @Autowired
    private IWorkflowWorkflowService workflowWorkflowService;
    @Autowired
    private IWorkflowStore workflowStore;
    @Autowired
    private IScriptServiceStore scriptServiceStore;
    @Autowired
    private IWorkflowActivityService workflowActivityService;

    private ApplicationContext applicationContext;
	@Override
	@Transactional
	public WorkflowToken startProcessByCode(String code, String bizKey){
		// TODO Auto-generated method stub
		QueryWrapper<WorkflowProcess> processQuery=new QueryWrapper<WorkflowProcess>();
		processQuery.eq("biz_key", bizKey);
		processQuery.inSql("workflow_workflow_id","select id from workflow_workflow where code='"+code+"'");
		long count=count(processQuery);
		if(count>0) {
			throw new RuntimeException("工作流已经存在，请不要重复提交");
		}
		WorkflowWorkflow workflowWorkflow=workflowWorkflowService.getMaxVersionWorkflowWorkflowByCode(code);
		WorkflowDef workflowDef=workflowStore.get(workflowWorkflow.getId());
		WorkflowProcess workflowProcess=new WorkflowProcess();
		workflowProcess.setWorkflowWorkflowId(workflowWorkflow.getId());
		workflowProcess.setStartDate(new Timestamp(System.currentTimeMillis()));
		workflowProcess.setBizKey(bizKey);
		workflowProcess.setState("DR");
		insert(workflowProcess);
		Expression startEventExpression=workflowDef.getStartEventExpression();
		if(startEventExpression!=null) {
			Map<String,Object> paraMap=new HashMap<String,Object>();
			WorkflowContext workflowContext=new WorkflowContext();
			paraMap.put("workflowContext", workflowContext);
			workflowContext.setWorkflowProcess(workflowProcess);
			workflowContext.setBizKey(bizKey);
			scriptServiceStore.getScriptService(startEventExpression).eval(startEventExpression.getScript(), paraMap);
		}
		workflowProcess.setState("IP");
		update(workflowProcess);
		WorkflowToken workflowToken=internalStartProcess(workflowProcess);
		return workflowToken;
	}
	
	@Transactional
	protected WorkflowToken internalStartProcess(WorkflowProcess workflowProcess) {
		WorkflowActivity workflowActivity=workflowActivityService.getStartActivity(workflowProcess.getWorkflowWorkflowId());
		WorkflowDef workflowDef=workflowStore.get(workflowActivity.getWorkflowWorkflowId());
		NodeDef nodeDef=workflowDef.getNodeDefById(workflowActivity.getNodeId());
		INodeService  nodeService=(INodeService)applicationContext.getBean(nodeDef.getType()+"NodeService");
		WorkflowContext workflowContext=new WorkflowContext();
		workflowContext.setWorkflowProcess(workflowProcess);
		workflowContext.setNodeDef(nodeDef);
		workflowContext.setWorkflowActivity(workflowActivity);
		workflowContext.setBizKey(workflowProcess.getBizKey());
		nodeService.start(workflowContext);
		return workflowContext.getWorkflowToken();
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		// TODO Auto-generated method stub
		this.applicationContext=applicationContext;
	}
}